package com.jy.datapipeline.common.util;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class BeanFactoryUtil implements BeanFactoryPostProcessor, BeanDefinitionRegistryPostProcessor {

    private static BeanDefinitionRegistry registry;

    public static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(@NotNull ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanFactoryUtil.beanFactory = beanFactory;
    }

    @Override
    public void postProcessBeanDefinitionRegistry(@NotNull BeanDefinitionRegistry registry) throws BeansException {
        BeanFactoryUtil.registry = registry;
    }

    /**
     *
     * 主动向Spring容器中获取bean
     *
     * @param clazz           注册的bean的类性
     * @param args            构造方法的必要参数，顺序和类型要求和clazz中定义的一致
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz, Object... args) {
        return beanFactory.getBean(clazz, args);
    }

    public static <T> T getBean(String beanName, Class<T> clazz) {
        return beanFactory.getBean(beanName, clazz);
    }
    
    /**
     * 主动向Spring容器中注册bean
     *
     * @param beanName           BeanName
     * @param clazz              注册的bean的类性
     * @param args               构造方法的必要参数，顺序和类型要求和clazz中定义的一致
     * @param <T>
     * @return 返回注册到容器中的bean对象
     */
    public static <T> T registerBean(String beanName, Class<T> clazz, Object... args) {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
        for (Object arg : args) {
            beanDefinitionBuilder.addConstructorArgValue(arg);
        }
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        registry.registerBeanDefinition(beanName, beanDefinition);
        return beanFactory.getBean(beanName, clazz);
    }
}